{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Lumped Elements Circuits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this notebook, we construct various network from basic lumped elements (resistor, capacitor, inductor), with the 'classic' and the `Circuit` approach. Generally the `Circuit` approach is more verbose than the 'classic' way for building a circuit. However, as the circuit complexity increases, in particular when components are connected in parallel, the `Circuit` approach is interesting as it increases the readability of the code. Moreover, `Circuit` object can be plotted using its `plot_graph()` method, which is useful to rapidly control if the circuit is built as expected. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np # for np.allclose() to check that S-params are similar\n", "\n", "import skrf as rf\n", "\n", "rf.stylely()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## LC Series Circuit" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this section we reproduce a simple equivalent model of a capacitor $C$, as illustrated by the figure below:\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# reference LC circuit made in Designer\n", "LC_designer = rf.Network('designer_capacitor_30_80MHz_simple.s2p')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# scikit-rf: manually connecting networks\n", "line = rf.media.DefinedGammaZ0(frequency=LC_designer.frequency, z0=50)\n", "LC_manual = line.inductor(24e-9) ** line.capacitor(70e-12)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# scikit-rf: using Circuit builder\n", "port1 = rf.Circuit.Port(frequency=LC_designer.frequency, name='port1', z0=50)\n", "port2 = rf.Circuit.Port(frequency=LC_designer.frequency, name='port2', z0=50)\n", "cap = rf.Circuit.SeriesImpedance(frequency=LC_designer.frequency, name='cap', z0=50,\n", " Z=1/(1j*LC_designer.frequency.w*70e-12))\n", "ind = rf.Circuit.SeriesImpedance(frequency=LC_designer.frequency, name='ind', z0=50,\n", " Z=1j*LC_designer.frequency.w*24e-9)\n", "\n", "# NB: it is also possible to create 2-port lumped elements like:\n", "# line = rf.media.DefinedGammaZ0(frequency=LC_designer.frequency, z0=50)\n", "# cap = line.capacitor(70e-12, name='cap')\n", "# ind = line.inductor(24e-9, name='ind')\n", "\n", "connections = [\n", " [(port1, 0), (cap, 0)],\n", " [(cap, 1), (ind, 0)],\n", " [(ind, 1), (port2, 0)]\n", "]\n", "circuit = rf.Circuit(connections)\n", "LC_from_circuit = circuit.network" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# testing the equivalence of the results\n", "print(np.allclose(LC_designer.s, LC_manual.s))\n", "print(np.allclose(LC_designer.s, LC_from_circuit.s))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "circuit.plot_graph(network_labels=True, edge_labels=True, port_labels=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A More Advanced Equivalent Model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this section we reproduce an equivalent model of a capacitor $C$, as illustrated by the figure below:\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Reference results from ANSYS Designer\n", "LCC_designer = rf.Network('designer_capacitor_30_80MHz_adv.s2p')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# scikit-rf: usual way, but this time this is more tedious to deal with connection and port number\n", "freq = LCC_designer.frequency\n", "line = rf.media.DefinedGammaZ0(frequency=freq, z0=50)\n", "elements1 = line.resistor(1e-2) ** line.inductor(24e-9) ** line.capacitor(70e-12)\n", "elements2 = line.resistor(20e6)\n", "T_in = line.tee()\n", "T_out = line.tee()\n", "ntw = rf.connect(T_in, 1, elements1, 0)\n", "ntw = rf.connect(ntw, 2, elements2, 0)\n", "ntw = rf.connect(ntw, 1, T_out, 1)\n", "ntw = rf.innerconnect(ntw, 1, 2)\n", "LCC_manual = ntw ** line.shunt_capacitor(50e-12)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# scikit-rf: using Circuit builder\n", "freq = LCC_designer.frequency\n", "port1 = rf.Circuit.Port(frequency=freq, name='port1', z0=50)\n", "port2 = rf.Circuit.Port(frequency=freq, name='port2', z0=50)\n", "line = rf.media.DefinedGammaZ0(frequency=freq, z0=50)\n", "cap = line.capacitor(70e-12, name='cap')\n", "ind = line.inductor(24e-9, name='ind')\n", "res_series = line.resistor(1e-2, name='res_series')\n", "res_parallel = line.resistor(20e6, name='res_parallel')\n", "cap_shunt = line.capacitor(50e-12, name='cap_shunt')\n", "ground = rf.Circuit.Ground(frequency=freq, name='ground', z0=50)\n", "\n", "connections = [\n", " [(port1, 0), (res_series, 0), (res_parallel, 0)],\n", " [(res_series, 1), (cap, 0)],\n", " [(cap, 1), (ind, 0)],\n", " [(ind, 1), (cap_shunt, 0), (res_parallel, 1), (port2, 0)],\n", " [(cap_shunt, 1), (ground, 0)],\n", "]\n", "circuit = rf.Circuit(connections)\n", "LCC_from_circuit = circuit.network" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# testing the equivalence of the results\n", "print(np.allclose(LCC_designer.s, LCC_manual.s))\n", "print(np.allclose(LCC_designer.s, LCC_from_circuit.s))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "circuit.plot_graph(network_labels=True, edge_labels=True, port_labels=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pass band filter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below we construct a pass-band filter, from an example given in [Microwaves101](https://www.microwaves101.com/encyclopedias/lumped-element-filter-calculator):" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Reference result calculated from Designer\n", "passband_designer = rf.Network('designer_bandpass_filter_450_550MHz.s2p')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# scikit-rf: the filter by cascading all lumped-elements\n", "freq = passband_designer.frequency\n", "passband_manual = line.shunt_capacitor(25.406e-12) ** line.shunt_inductor(4.154e-9) ** \\\n", " line.capacitor(2.419e-12) ** line.inductor(43.636e-9) ** \\\n", " line.shunt_capacitor(25.406e-12) ** line.shunt_inductor(4.154e-9)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# scikit-rf: the filter with the Circuit builder\n", "freq = passband_designer.frequency\n", "line = rf.media.DefinedGammaZ0(frequency=freq)\n", "C1 = line.capacitor(25.406e-12, name='C1')\n", "C2 = line.capacitor(2.419e-12, name='C2')\n", "C3 = line.capacitor(25.406e-12, name='C3')\n", "L1 = line.inductor(4.154e-9, name='L1')\n", "L2 = line.inductor(43.636e-9, name='L2')\n", "L3 = line.inductor(4.154e-9, name='L3')\n", "port1 = rf.Circuit.Port(frequency=freq, name='port1', z0=50)\n", "port2 = rf.Circuit.Port(frequency=freq, name='port2', z0=50)\n", "ground = rf.Circuit.Ground(frequency=freq, name='ground', z0=50)\n", "\n", "connections = [\n", " [(port1, 0), (C1, 0), (L1, 0), (C2, 0)],\n", " [(C2, 1), (L2, 0)],\n", " [(L2, 1), (C3, 0), (L3, 0), (port2, 0)],\n", " [(C1, 1), (C3, 1), (L1, 1), (L3, 1), (ground, 0)],\n", "]\n", "\n", "circuit = rf.Circuit(connections)\n", "passband_circuit = circuit.network\n", "passband_circuit.name = 'Pass-band circuit'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "passband_circuit.plot_s_db(m=0, n=0, lw=2)\n", "passband_circuit.plot_s_db(m=1, n=0, lw=2)\n", "passband_designer.plot_s_db(m=0, n=0, lw=2, ls='-.')\n", "passband_designer.plot_s_db(m=1, n=0, lw=2, ls='-.')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "circuit.plot_graph(network_labels=True, port_labels=True, edge_labels=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3.10.6 ('.venv': venv)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.6" }, "vscode": { "interpreter": { "hash": "637c323cf467337602e9974a89cb4d3fc95fac3ef875a73e62754f8e768d8de7" } } }, "nbformat": 4, "nbformat_minor": 4 }